package cn.lxh.ymcc.service.impl;


import cn.lxh.ymcc.constants.CommonConstants;
import cn.lxh.ymcc.constants.SmsCodeConstants;
import cn.lxh.ymcc.constants.YmccError;
import cn.lxh.ymcc.domain.MessageSms;
import cn.lxh.ymcc.domain.User;
import cn.lxh.ymcc.dto.RedisRegisterDto;
import cn.lxh.ymcc.exception.GlobalException;
import cn.lxh.ymcc.feign.UserFeignClient;
import cn.lxh.ymcc.service.IMessageSmsService;
import cn.lxh.ymcc.service.IVerifyCodeService;
import cn.lxh.ymcc.util.AssertUtil;
import cn.lxh.ymcc.util.StrUtils;
import cn.lxh.ymcc.util.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IMessageSmsService iMessageSmsService;

    @Autowired
    private SmsCodeConstants smsCodeConstants;
    @Autowired
    private UserFeignClient userFeignClient;

    @Override
    public String imageCode(String key) {
       /* if(!StringUtils.hasLength(key)){
            throw new BusinessException("key不能为空！！！");
        }*/
//        (每次都是直接生成新的，但是要覆盖前面的)
//        。生成code = 9527
        String code = StrUtils.getRandomString(4);
        RedisRegisterDto newRedisRegisterDto = new RedisRegisterDto(code,null);
//        。保存redis，设置过期时间  key是什么==前端请求给我传递的UUID
        redisTemplate.opsForValue().set(key,//前端传递的UUID
                newRedisRegisterDto, //图片中的码儿
                5,//过期时间
                TimeUnit.MINUTES);//过期时间的单位
//        。使用2D引擎把code画成图
//        。把图使用Base64编码成字符串
//        。返回Base64编码的字符串
        String code1 = newRedisRegisterDto.getCode();
        return VerifyCodeUtils.verifyCode(100,40,code1);
    }
    /**
     * 发送短信
     * 非空校验 和格式正式
     *      断言-自定义-判断格式
     *判断这个电话是否层已经发过验证码
     * -从redis里面查询
     *     -redis里面有||时间没到。抛异常，请稍后再试
     *     -过了前端的时间验证码，但是redis里面还有。重新发送
     *  没有发过验码
     *      生成验证码
     *      存到redis中
     *
     *      发送短信
     *保存到数据库
     *
     * @param mobile
     */
    @Override
    public void sendSmsCode(String mobile) {

        AssertUtil.isNotEmpty(mobile, YmccError.COMMON_PHONE_NO_EMPTY.getMessage());

        AssertUtil.isPhone(mobile, YmccError.COMMON_PHONE_ILLEGAL.getMessage());



        String key = String.format(CommonConstants.REGISTER_PHONE_PRIFIX,mobile);
        log.info(key);

        Object o = redisTemplate.opsForValue().get(key);
        RedisRegisterDto redisRegisterDto = (RedisRegisterDto) o;

        String code=null;
        Date date = new Date();
        if (redisRegisterDto!=null){
//            这个验证码还在redis中
            boolean outTime = date.getTime() - redisRegisterDto.getTime() > 100*1000;
            AssertUtil.isTrue(outTime,YmccError.COMMON_SERIOUS.getMessage());
            code = redisRegisterDto.getCode();
        }else {
           code = StrUtils.getRandomString(smsCodeConstants.getSize());
        }
        RedisRegisterDto newRedisRegisterDto = new RedisRegisterDto(code, date.getTime());
        redisTemplate.opsForValue().set(key,newRedisRegisterDto,5,TimeUnit.MINUTES);

        String message = String.format(smsCodeConstants.getSmsmessage(),code);
        log.info(message);
        /**
         * 黑名单
         */
        User user = userFeignClient.selectByPhone(mobile);
        if (user !=null){
            Long bitState = user.getBitState();
            if( bitState<=1){
                throw new RuntimeException("黑名单然登录");
            }
        }
        saveMessage(date,code,message);

    }

    /**
     * 保存数据到数据库
     *  时间
     *  code
     *  message
     */
    private void saveMessage(Date date,String code ,String message) {
        MessageSms sms = new MessageSms();
        sms.setSendTime(date);
        sms.setContent(message);
        sms.setTitle("短信验证码");
//        ip地址
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String ip = request.getRemoteAddr();
        sms.setIp(ip);
        iMessageSmsService.insert(sms);
    }
}
